package com.liuwei.spring.cloud.configuration;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.DateDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.liuwei.spring.cloud.framework.feigns.provider.FeignLogFilter;
import jakarta.servlet.DispatcherType;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.filter.CommonsRequestLoggingFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * @author : evan.liu
 * @version V1.0
 * @Description:
 * @date Date : 2022年05月01日 1:32 上午
 */
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
//public class WebConfiguration extends WebMvcConfigurationSupport
//如果我们在项目中去继承WebMvcConfigurationSupport这个类的话,那么springboot中的mvc自动配置会失效

    /**
     * MappingJackson2HttpMessageConverter是springboot中默认的Json消息转换器
     * https://blog.csdn.net/Heron22/article/details/109512976
     * @return
     */
    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(ObjectMapper defaultObjectMapper) {
        // 系统默认时区 -> 获取系统时区
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();

        // 设置入站时间格式,效果同 @DateTimeFormat(pattern = "")
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss")));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));

        javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss")));
        javaTimeModule.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        javaTimeModule.addDeserializer(LocalTime.class,new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
        defaultObjectMapper.registerModule(javaTimeModule);

        // 设置默认的时间反序列化格式
        SimpleModule javaDateModule = new SimpleModule();
        //使用 yaml 文件配置
        //javaDateModule.addSerializer(Date.class, new DateSerializer(false,new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")));

        DateDeserializers.DateDeserializer base = new DateDeserializers.DateDeserializer();
        SimpleDateFormat standard = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        DateDeserializers.DateDeserializer standardFormat = new DateDeserializers.DateDeserializer(base,standard,standard.toPattern());
        javaDateModule.addDeserializer(Date.class, standardFormat);

        SimpleDateFormat mills = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        DateDeserializers.DateDeserializer millsFormat = new DateDeserializers.DateDeserializer(base,mills,mills.toPattern());
        javaDateModule.addDeserializer(Date.class, millsFormat);
        defaultObjectMapper.registerModule(javaDateModule);

        // 设置全局的反序列化方式 / 使用 yaml 文件配置
        // objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        // objectMapper.setTimeZone(timezone);
        defaultObjectMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL,true);
        defaultObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        // @JSONFormat 默认GMT+0 且优先级 > 全局配置
        // 设置指定包名下的 @JSONFormat 的默认时区(仅限制项目自定义的类)
        //String packageName = CloudJarApplication.class.getPackage().getName();
        //ReflectHelper.resetJsonFormatDefaultTimeZone(packageName,timezone);
        mappingJackson2HttpMessageConverter.setObjectMapper(defaultObjectMapper);
        return mappingJackson2HttpMessageConverter;
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowCredentials(true)
                .allowedHeaders("*")
                .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS")
                .maxAge(3600L);
    }


    /*@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        super.addResourceHandlers(registry);
    }*/

    /*@Bean
    public FilterRegistrationBean registerHttpTraceFilter() {
        //TODO:与DeferredResult不兼容
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new HttpTraceFilter());
        registration.setDispatcherTypes(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST);
        registration.addUrlPatterns("/api/*");
        registration.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
        return registration;
    }*/

    //@Bean
    /*public FilterRegistrationBean registerTagResponseFilter() {
        //TODO:与DeferredResult不兼容
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new TagResponseFilter());
        registration.setDispatcherTypes(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST);
        registration.addUrlPatterns("/*");
        registration.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
        return registration;
    }*/

    @Bean
    public CommonsRequestLoggingFilter logFilter() {
        // logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG
        CommonsRequestLoggingFilter loggingFilter = new CommonsRequestLoggingFilter();
        loggingFilter.setIncludeClientInfo(true);
        loggingFilter.setIncludeQueryString(true);
        loggingFilter.setIncludeHeaders(true);
        loggingFilter.setIncludePayload(true);
        loggingFilter.setMaxPayloadLength(20480);
        loggingFilter.setBeforeMessagePrefix("REQUEST START: ");
        loggingFilter.setAfterMessagePrefix("REQUEST END: ");
        return loggingFilter;
    }

    @Bean
    public FilterRegistrationBean registerFeignLogFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new FeignLogFilter());
        registration.setDispatcherTypes(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST);
        registration.addUrlPatterns("/api/*");
        registration.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
        return registration;
    }
}

